// -------------------------------------------
// Tools
(function(window, undefined) {
	var Tools = {
		getRandom: function(min, max) {
			return Math.floor(Math.random() * (max - min + 1) + min);
		}
	}

	window.Tools = Tools;
})(window, undefined);


// -------------------------------------------
// Food
(function(window, undefined) {
	function Food(map, option) {
		option = option || {};
		this.x = option.x || 0;
		this.y = option.y || 0;
		this.width = option.width || 20;
		this.height = option.height || 20;
		this.background = option.background || 'green';
		this.map = map;
		this.food = document.createElement('div');
	}

	Food.prototype = {
		constructor: Food,
		render: function() {
			var food = this.food;
			this.map.appendChild(food);
			this.randomXy();
			food.style.width = this.width + 'px';
			food.style.height = this.height + 'px';
			food.style.left = this.x * this.width + 'px';
			food.style.top = this.y * this.height + 'px';
			food.style.background = this.background;
			food.style.position = 'absolute';
		},
		randomXy: function() {
			this.x = Tools.getRandom(0, this.map.offsetWidth / this.width -1);
			this.y = Tools.getRandom(0, this.map.offsetHeight / this.height - 1);
		},
	}

	window.Food = Food;
})(window, undefined);	
// 在闭包结束的时候需要加上;否则会影响下一个闭包的调用
/* window和undefined的意义

	1. 传入参数时，可以在代码压缩的时候，对参数进行简化
	2. undefined可以在老版本中被重新赋值，传入undefined可以防止被重新定义，以至于代码出错

*/


// ---------------------------------------------
// Snack
(function(window, undefined) {
	var that, body;
	var bodySet = [];

	function Snack(map, food, option) {
		option = option || {};
		this.width = option.width || 20;
		this.height = option.height || 20;
		this.map = map;
		this.body = [
			{x: 3, y: 3, background: 'red'},
			{x: 2, y: 3, background: 'green'},
			{x: 1, y: 3, background: 'green'},
		];
		this.rear;
		this.decration = 'right';

		that = this;
		body = this.body;
	}

	Snack.prototype = {
		constructor: Snack,
		render: function() {
			remove();
			for (let i = 0, len = body.length; i < len; i++) {
				var div = document.createElement('div');
				div.style.width = this.width + 'px';
				div.style.height = this.height + 'px';
				div.style.left = body[i].x * this.width + 'px';
				div.style.top = body[i].y * this.height + 'px';
				div.style.background = body[i].background;
				div.style.border = '1px solid #ccc';
				div.style.position = 'absolute';
				this.map.appendChild(div);
				bodySet.push(div);
			}
		},
		move: function() {
			var len = body.length - 1;
			this.rear = {x: body[len].x, y: body[len].y};
			// 1. 先渲染身体
			for (let i = len ; i >= 1; i--) {
				body[i].x = body[i - 1].x;
				body[i].y = body[i - 1].y;
			}
			// 2. 根据方向渲染头部
			switch(this.decration) {
				case 'up': 
					body[0].y--;
					break;
				case 'down':
					body[0].y++; 
					break;
				case 'left':
					body[0].x--; 
					break;
				case 'right':
					body[0].x++; 
					break;
			}
			this.eatFood();
			this.render();
		},
		eatFood: function() {
			if(this.body[0].x == food.x && this.body[0].y == food.y) {
				var newBody = {
					x: that.rear.x,
					y: that.rear.y,
					background: 'green'
				};
				body.push(newBody);
				food.randomXy();
				food.render();
			}
		},
	}

	// 清除以前的创建的div，即清除移动痕迹
	function remove() {
		if (bodySet.length) {
			for (let i = 0, len = body.length; i < len; i++) {
				if (bodySet[0]) {
					this.map.removeChild(bodySet[0]);
					bodySet.shift();
				}
			}
		} else {
			return;
		}
	}

	window.Snack = Snack;
})(window, undefined);


// ---------------------------------------------
// Map 
(function(window, undefined) {
	var that;

	function Map(option) {
		option = option || {};
		this.snack = option.snack;
		this.food = option.food;
		this.map = option.map;
		this.time;
		
		that = this;

		this.render();
		this.start();
	}

	Map.prototype = {
		constructor: Map,
		render: function() {
			this.snack.render();
			this.food.render();
		},
		start: function() {
			this.time = setInterval(function() {
				that.snack.move();
				that.isGameOver();
			}, 200);
		},
		isGameOver: function() {
			var headX = this.snack.body[0].x;
			var headY = this.snack.body[0].y;
			if (headX < 0 || headX > this.map.offsetWidth / this.snack.width - 1) {
				clearInterval(this.time);
				alert('游戏失败');
			}
			if (headY < 0 || headY > this.map.offsetHeight / this.snack.height - 1) {
				clearInterval(this.time);
				alert('游戏失败');
			}
		},
	}

	// 开启点击事件
	function control() {
		document.addEventListener('keydown', function(e) {
			e = e || window.event;
			var keyCode = e.keyCode;	// 87 83 65 68
			switch(keyCode) {
				case 87: 
					that.snack.decration = 'up';
					break;
				case 83: 
					that.snack.decration = 'down';
					break;
				case 65: 
					that.snack.decration = 'left';
					break;
				case 68: 
					that.snack.decration = 'right';
					break;
				default: 
					break;
			}
		}, false);
	}
	control();

	window.Map = Map;
})(window, undefined);


var map = document.getElementById('map');
var food = new Food(map);
var snack = new Snack(map, food);
var div = new Map({
	food: food,
	snack: snack,
	map: map
});